package com.c2dm.data;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;

import sporteam.web.client.AEuser;

import com.c2dm.servlets.SendServlet;

public class MessageUtil
{
	private final static String AUTH = "authentication";

	private static final String UPDATE_CLIENT_AUTH = "Update-Client-Auth";

	public static final String PARAM_REGISTRATION_ID = "registration_id";

	public static final String PARAM_DELAY_WHILE_IDLE = "delay_while_idle";

	public static final String PARAM_COLLAPSE_KEY = "collapse_key";

	private static final String UTF8 = "UTF-8";
	
	private static final Logger log = Logger.getLogger(SendServlet.class.getName());

	//given authentication token,registationId and a string, sends a c2dm push notification to device
	public static int sendMessage(String auth_token, String registrationId,String message) throws IOException
	{
		StringBuilder postDataBuilder = new StringBuilder();
		postDataBuilder.append(PARAM_REGISTRATION_ID).append("=")
				.append(registrationId);
		postDataBuilder.append("&").append(PARAM_COLLAPSE_KEY).append("=")
				.append("0");
		postDataBuilder.append("&").append("data.payload").append("=")
				.append(URLEncoder.encode(message, UTF8));

		byte[] postData = postDataBuilder.toString().getBytes(UTF8);

		// Hit the dm URL.

		if(auth_token == null)
		{
			auth_token = AuthenticationUtil.getToken(SecureStorage.USER,SecureStorage.PASSWORD);
		}
		
		URL url = new URL("https://android.clients.google.com/c2dm/send");
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setDoOutput(true);
		conn.setUseCaches(false);
		conn.setRequestMethod("POST");
		conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
		conn.setRequestProperty("Content-Length",Integer.toString(postData.length));
		conn.setRequestProperty("Authorization", "GoogleLogin auth=" + auth_token);
				
		OutputStream out = conn.getOutputStream();
		out.write(postData);
		out.close();

		int responseCode = conn.getResponseCode();
		return responseCode;
	}
	
	public static String sendInformativeMessage(String facebook_id,String message) throws IOException 
	{
	
		PersistenceManager pm = sporteam.common.PMF.get().getPersistenceManager();
		AEuser user = pm.getObjectById(AEuser.class, facebook_id);
		
		//get authentication token from c2dm servers
		String auth_key = AuthenticationUtil.getToken(SecureStorage.USER,SecureStorage.PASSWORD);
		
		//get registration ID from user
		String registrationId = user.getReg_id();
		
		log.warning("Used authentication token:" + auth_key);
		log.warning("Used registration id:" + registrationId);

		// Send a sync message to this Android device.
		StringBuilder postDataBuilder = new StringBuilder();
		postDataBuilder.append(PARAM_REGISTRATION_ID).append("=")
				.append(registrationId);

		postDataBuilder.append("&").append(PARAM_COLLAPSE_KEY).append("=")
				.append("0");

		postDataBuilder.append("&").append("data.payload").append("=")
				.append(URLEncoder.encode(message, UTF8));

		byte[] postData = postDataBuilder.toString().getBytes(UTF8);

		// Hit the C2DMdm URL.

		URL url = new URL("https://android.clients.google.com/c2dm/send");

		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setDoOutput(true);
		conn.setUseCaches(false);
		conn.setRequestMethod("POST");
		conn.setRequestProperty("Content-Type",
				"application/x-www-form-urlencoded;charset=UTF-8");
		conn.setRequestProperty("Content-Length",
				Integer.toString(postData.length));
		conn.setRequestProperty("Authorization", "GoogleLogin auth=" + auth_key);

		OutputStream out = conn.getOutputStream();
		out.write(postData);
		out.close();

		int responseCode = conn.getResponseCode();

		log.info(String.valueOf(responseCode));
		// Validate the response code

		if (responseCode == 401 || responseCode == 403)
		{
			// The token is too old - return false to retry later, will
			// fetch the token
			// from DB. This happens if the password is changed or token
			// expires. Either admin
			// is updating the token, or Update-Client-Auth was received by
			// another server,
			// and next retry will get the good one from database.
			log.severe("Unauthorized - need token / or token not valid.");
		}

		// Check for updated token header
		String updatedAuthToken = conn.getHeaderField(UPDATE_CLIENT_AUTH);
		if (updatedAuthToken != null && !auth_key.equals(updatedAuthToken)) 
		{
			log.warning("Got updated auth token from datamessaging servers: " + updatedAuthToken);
		}

		String responseLine = new BufferedReader(new InputStreamReader(conn.getInputStream())).readLine();
				
		// NOTE: You *MUST* use exponential backoff if you receive a 503
		// response code.
		// Since App Engine's task queue mechanism automatically does this
		// for tasks that
		// return non-success error codes, this is not explicitly
		// implemented here.
		// If we weren't using App Engine, we'd need to manually implement
		// this.
		if (responseLine == null || responseLine.equals("")) 
		{
			log.warning("Got " + responseCode
					+ " response from Google AC2DM endpoint.");
			throw new IOException(
					"Got empty response from Google AC2DM endpoint.");
		}

		String[] responseParts = responseLine.split("=", 2);
		if (responseParts.length != 2)
		{
			log.warning("Invalid message from google: " + responseCode + " " + responseLine);
			throw new IOException("Invalid response from Google " + responseCode + " " + responseLine);
		}

		if (responseParts[0].equals("id"))
		{
			log.warning("Successfully sent data message to device: " + responseLine);
		}

		if (responseParts[0].equals("Error")) 
		{
			String err = responseParts[1];
			log.warning("Got error response from Google datamessaging endpoint: " + err);
			// No retry.
			throw new IOException(err);
		}
		return responseLine + " " + String.valueOf(responseCode);
	}
	
	public static int SendMsgToUser(String facebook_id)
	{
		
		return 42;
	}
}